package com.anjiplus.template.gaea.auth.modules.org.service.impl;

import com.anjiplus.template.gaea.common.MagicValueConstants;
import com.anji.plus.gaea.bean.TreeNode;
import com.anji.plus.gaea.constant.Enabled;
import com.anji.plus.gaea.constant.GaeaConstant;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anjiplus.template.gaea.auth.modules.org.controller.dto.GaeaOrgDTO;
import com.anjiplus.template.gaea.auth.modules.org.controller.param.GaeaOrgParam;
import com.anjiplus.template.gaea.auth.modules.org.dao.GaeaOrgMapper;
import com.anjiplus.template.gaea.auth.modules.org.dao.entity.GaeaOrg;
import com.anjiplus.template.gaea.auth.modules.org.service.GaeaOrgService;
import com.anjiplus.template.gaea.auth.modules.role.dao.GaeaRoleMapper;
import com.anjiplus.template.gaea.auth.modules.role.dao.entity.GaeaRole;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 组织(GaeaOrg)ServiceImpl
 *
 * @author lr
 * @since 2021-02-02 13:37:33
 */
@Service
public class GaeaOrgServiceImpl implements GaeaOrgService {

    @Autowired
    private GaeaOrgMapper gaeaOrgMapper;

    @Autowired
    private GaeaRoleMapper gaeaRoleMapper;

    @Override
    public GaeaBaseMapper<GaeaOrg> getMapper() {
        return gaeaOrgMapper;
    }

    /**
     * 当机构编码不为空时，要查出当前组织的下属组织
     *
     * @param param   查询参数
     * @param queryWrapper 基本查询条件
     * @return
     */
    @Override
    public Wrapper<GaeaOrg> extensionWrapper(GaeaOrgParam param, QueryWrapper<GaeaOrg> queryWrapper) {
        if (StringUtils.isNotBlank(param.getCode())) {
            queryWrapper.and(wrapper ->wrapper.or().lambda().eq(GaeaOrg::getOrgParentCode, param.getCode()).or().eq(GaeaOrg::getOrgCode, param.getCode()));
        }
        return queryWrapper;
    }

    @Override
    public List<GaeaOrg> queryAllOrg() {
        LambdaQueryWrapper<GaeaOrg> wrapper = Wrappers.lambdaQuery();
        wrapper.select(GaeaOrg::getOrgCode, GaeaOrg::getOrgName)
                .eq(GaeaOrg::getEnabled, Enabled.YES.getValue());
        return gaeaOrgMapper.selectList(wrapper);
    }

    @Override
    public Boolean saveOrUpdateOrg(GaeaOrgDTO gaeaOrgDTO) {
        //设置父类机构名称
        if (StringUtils.isNotEmpty(gaeaOrgDTO.getOrgParentCode())) {
            LambdaQueryWrapper<GaeaOrg> wrapper = Wrappers.lambdaQuery();
            wrapper.select(GaeaOrg::getOrgCode, GaeaOrg::getOrgName)
                    .eq(GaeaOrg::getOrgCode, gaeaOrgDTO.getOrgParentCode());
            List<GaeaOrg> parentOrgList = gaeaOrgMapper.selectList(wrapper);
            gaeaOrgDTO.setOrgParentName(parentOrgList.get(0).getOrgName());
        } else {
            gaeaOrgDTO.setOrgParentCode(MagicValueConstants.STRING_ZERO);
        }
        GaeaOrg gaeaOrg = new GaeaOrg();
        BeanUtils.copyProperties(gaeaOrgDTO, gaeaOrg);
        if (null != gaeaOrgDTO.getId()) {
            gaeaOrgMapper.updateById(gaeaOrg);
        } else {
            gaeaOrgMapper.insert(gaeaOrg);
        }
        return true;
    }

    @Override
    public List<TreeNode> tree(boolean hasRole) {

        //所有目录
        LambdaQueryWrapper<GaeaOrg> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.eq(GaeaOrg::getEnabled, Enabled.YES.getValue());
        List<GaeaOrg> orgList = gaeaOrgMapper.selectList(queryWrapper);

        //查询所有启用角色
        LambdaQueryWrapper<GaeaRole> roleWrapper=Wrappers.lambdaQuery();
        roleWrapper.eq(GaeaRole::getEnabled,Enabled.YES.getValue());
        List<GaeaRole> gaeaRoles = gaeaRoleMapper.selectList(roleWrapper);

        //机构和角色下的分组（机构对应角色列表）
        Map<String, List<TreeNode>> roleOrgMap = new HashMap<>(2);
        if (hasRole) {
            //当包含角色时，添加机构与角色分组
            roleOrgMap.putAll(gaeaRoles.stream().filter(gaeaRole -> StringUtils.isNotBlank(gaeaRole.getOrgCode()))
                    .collect(Collectors.groupingBy(GaeaRole::getOrgCode, Collectors.mapping(gaeaRole -> {
                        TreeNode treeNode = new TreeNode();
                        treeNode.setId(gaeaRole.getOrgCode() + GaeaConstant.REDIS_SPLIT + gaeaRole.getRoleCode());
                        treeNode.setLabel(gaeaRole.getRoleName());
                        treeNode.setChildren(new ArrayList<>());
                        return treeNode;
                    }, Collectors.toList()))));
        }

        LambdaQueryWrapper<GaeaOrg> wrapper = Wrappers.lambdaQuery();
        wrapper.isNull(GaeaOrg::getOrgParentCode).or().eq(GaeaOrg::getOrgParentCode, "");
        //root目录
        List<GaeaOrg> rootGaeaOrgList = gaeaOrgMapper.selectList(wrapper);

        List<TreeNode> result = rootGaeaOrgList.stream().map(rootGaeaOrg -> {
            TreeNode treeNode = createTreeNode(orgList, roleOrgMap, rootGaeaOrg);
            return treeNode;
        }).collect(Collectors.toList());

        return result;
    }


    /**
     * 设置子机构
     *
     * @param treeNode
     * @param gaeaOrgList
     */
    private void setOrgChildren(TreeNode treeNode, List<GaeaOrg> gaeaOrgList, Map<String, List<TreeNode>> roleOrgMap) {

        gaeaOrgList.stream()
                .filter(gaeaOrg -> StringUtils.equals(treeNode.getId(), gaeaOrg.getOrgParentCode()))
                .forEach(gaeaOrg -> {
                    TreeNode treeNodeTemp = createTreeNode(gaeaOrgList, roleOrgMap, gaeaOrg);
                    treeNode.getChildren().add(treeNodeTemp);
                });
    }

    private TreeNode createTreeNode(List<GaeaOrg> gaeaOrgList, Map<String, List<TreeNode>> roleOrgMap, GaeaOrg gaeaOrg) {
        TreeNode treeNodeTemp = new TreeNode();
        treeNodeTemp.setId(gaeaOrg.getOrgCode());
        treeNodeTemp.setLabel(gaeaOrg.getOrgName());
        treeNodeTemp.setChildren(new ArrayList<>());
        //当组织与角色对应
        if (!CollectionUtils.isEmpty(roleOrgMap) && roleOrgMap.containsKey(gaeaOrg.getOrgCode())) {
            treeNodeTemp.getChildren().addAll(roleOrgMap.get(gaeaOrg.getOrgCode()));
        }
        //设置下级组织
        setOrgChildren(treeNodeTemp, gaeaOrgList, roleOrgMap);
        return treeNodeTemp;
    }
}
